package com.autumn.evaluator;

//

// * 提供编译的解析，并支持对已编译的表达式缓存，即运算解析
//

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.function.Function;

import com.autumn.evaluator.nodes.AbstractTreeNode;
import com.autumn.util.ArgumentNullException;
import com.autumn.util.DLinkedList;
import com.autumn.util.StringUtils;
import com.autumn.util.tuple.TupleTwo;

/**
 * 解析器
 */
public class Evaluator {

	/**
	 * 缓存集合
	 */
	private HashMap<String, AbstractTreeNode> caches;

	private Function<String, ILexerParse> lexerParseFactory;

	/**
	 * 获取或设置文法工厂
	 */
	public final Function<String, ILexerParse> getLexerParseFactory() {
		return lexerParseFactory;
	}

	public final void setLexerParseFactory(Function<String, ILexerParse> value) {
		if (value == null) {
			throw new ArgumentNullException("value is null");
		}
		lexerParseFactory = value;
	}

	/**
	 * 实例化 Evaluator 类新实例
	 */
	public Evaluator() {
		this(-1);
	}

	/**
	 * 实例化 Evaluator 类新实例
	 *
	 * @param capacity
	 *            缓存可包含的初始元素数
	 */
	public Evaluator(int capacity) {
		if (capacity > 0) {
			this.caches = new HashMap<>(capacity);
		} else {
			this.caches = new HashMap<>();
		}
		lexerParseFactory = exp -> new ValueLexerParse(exp);
	}

	/**
	 * 创建文法解析器
	 *
	 * @param expression
	 *            表达式
	 * @return
	 */
	private ILexerParse createLexerParse(String expression) {
		return lexerParseFactory.apply(expression);
	}

	/**
	 * 解析并返回结果
	 *
	 * @param expression
	 *            表达式
	 * @param context
	 *            上下文接口,可传入 null
	 * @return 返回 Variant 对象
	 */
	public final Variant parse(String expression, IContext context) {
		ParseContext tempVar = new ParseContext(context);
		return this.compiled(expression).parse(tempVar);
	}

	/**
	 * 编译并返回节点
	 *
	 * @param expression
	 *            表达式
	 * @return
	 */
	public final AbstractTreeNode compiled(String expression) {
		if (StringUtils.isNullOrBlank(expression)) {
			return AbstractTreeNode.createNullNode();
		}
		synchronized (this) {
			String key = expression.trim();
			AbstractTreeNode node = null;
			if (!((node = this.caches.get(key)) != null)) {
				ILexerParse parse = createLexerParse(expression);
				// parse.Language = this.getLanguage();
				// parse.LanguageConfigPath = this.getLanguageConfigPath();
				node = parse.compiled();
				this.caches.put(key, node);
			}
			return node;
		}
	}

	/**
	 * 读取标记集合
	 *
	 * @param expression
	 *            表达式
	 * @return
	 */
	public final DLinkedList<Token> readTokens(String expression) {
		Utils.checkNotNullOrEmpty("expression", expression);
		ILexerParse lexer = createLexerParse(expression);
		return lexer.readTokens();
	}

	/**
	 * 清除缓存
	 */
	public final void clear() {
		synchronized (this) {
			this.caches.clear();
		}
	}

	/**
	 * 移除缓存
	 *
	 * @param expression
	 *            表达式
	 * @return
	 */
	public final boolean remove(String expression) {
		if (expression == null) {
			throw new ArgumentNullException("expression");
		}
		boolean isSuccess = true;
		synchronized (this) {
			try {
				this.caches.remove(expression.trim());
			} catch (Exception e) {
				isSuccess = false;
			}
		}
		return isSuccess;
	}

	/**
	 * 编译并返回节点
	 *
	 * @param expression
	 *            表达式
	 * @param lexerParse
	 * @return
	 */
	public static AbstractTreeNode nodeCompiled(String expression, ILexerParse lexerParse) {
		if (StringUtils.isNullOrBlank(expression)) {
			return AbstractTreeNode.createNullNode();
		}
		if (lexerParse == null) {
			lexerParse = new ValueLexerParse(expression);
		}
		return lexerParse.compiled();
	}

	/**
	 * 编译并返回节点
	 *
	 * @param expression
	 *            表达式
	 * @param lexerParse
	 *            文法解析
	 * @return
	 */
	public static TupleTwo<AbstractTreeNode, Collection<Token>> nodeCompiledOfTokens(String expression,
			ILexerParse lexerParse) {
		if (StringUtils.isNullOrBlank(expression)) {
			return new TupleTwo<>(AbstractTreeNode.createNullNode(), new ArrayList<>());
		}
		if (lexerParse == null) {
			lexerParse = new ValueLexerParse(expression);
		}
		DLinkedList<Token> items = lexerParse.readTokens();
		NodeParse parse = new NodeParse(items, null);
		return new TupleTwo<>(parse.compiled(), items);
	}

	/**
	 * 编译并返回节点
	 *
	 * @param tokens
	 *            标记集合
	 * @return
	 */
	public static AbstractTreeNode nodeCompiled(Collection<Token> tokens) {
		Utils.checkNotNull("tokens", tokens);
		if (tokens.size() == 0) {
			return AbstractTreeNode.createNullNode();
		}
		for (Iterator<Token> iter = tokens.iterator(); iter.hasNext();) {
			if (iter.next() == null) {
				throw new ArgumentNullException("tokens", "tokens 存在 null 的元素。");
			}
		}
		DLinkedList<Token> link;
		if (tokens instanceof LinkedList) {
			link = (DLinkedList<Token>) tokens;
		} else {
			link = new DLinkedList<>(tokens);
		}
		NodeParse parse = new NodeParse(link, null);
		return parse.compiled();
	}

	/**
	 * 解析并返回结果
	 *
	 * @param expression
	 *            表达式
	 * @param lexerParse
	 *            解析器
	 * @param context
	 *            上下文接口,可传入 null
	 * @return 返回 Variant 对象
	 */
	public static Variant valueParse(String expression, ILexerParse lexerParse, IContext context) {
		return Evaluator.nodeCompiled(expression, lexerParse).parse(new ParseContext(context));
	}

	/**
	 * 解析并返回结果
	 *
	 * @param node
	 *            节点
	 * @param context
	 *            上下文接口,可传入 null
	 * @return 返回 Variant 对象
	 */
	public static Variant valueParse(AbstractTreeNode node, IContext context) {
		if (node == null) {
			throw new ArgumentNullException("node");
		}
		return node.parse(new ParseContext(context));
	}

	/**
	 * 解析并返回结果
	 *
	 * @param tokens
	 *            标记集合
	 * @param context
	 *            上下文接口,可传入 null
	 * @return 返回 Variant 对象
	 */
	public static Variant valueParse(Collection<Token> tokens, IContext context) {
		AbstractTreeNode node = Evaluator.nodeCompiled(tokens);
		return node.parse(new ParseContext(context));
	}
}